Resolver: Parallelize the import resolution loop - #158845
Resolver: Parallelize the import resolution loop#158845LorrensP-2158466 wants to merge 3 commits into
Conversation
|
Lets see what CI says. I have tried to add comments to changes to show my thought process behind them, but i'll make another pass here as well to be sure. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
17bd1cb to
9aa1069
Compare
This comment has been minimized.
This comment has been minimized.
9aa1069 to
a45ba86
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…r=<try> Resolver: Parallelize the import resolution loop
This comment has been minimized.
This comment has been minimized.
I'll think that I will extend them a bit and add a comment to the |
|
Updated the comments and used |
|
Benchmarking the changes in #160064. |
|
I'm also tempted to add extra methods for |
|
https://github.com/LorrensP-2158466/ref_mut/tree/main has the code for the miri tests, as you will see (and the comments in this pr explain) |
|
decided to create a |
This comment has been minimized.
This comment has been minimized.
At least right now it probably doesn't need to be atomic though. |
Again, we'll need to benchmark whether eliding this boolean assert even matters, considering that it's not even atomic. |
|
I'll split the |
Yes, after the |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Rebased to fix conflicts and cleanup the PR, it now contains:
@rustbot ready. |
I don't think we'll merge this part, given the unconvincing perf results from the linked PR and the amount of complexity/unsafety. |
| scope = next.get(); | ||
| macro_rules_scope.set(scope); | ||
| scope = *next.borrow(); | ||
| *macro_rules_scope.borrow_mut() = scope; |
There was a problem hiding this comment.
I'm not sure this is algorithmically correct.
We may need to protect a larger piece of logic by a lock, maybe the whole loop.
I need to think (but I'm busy this and next week).
There was a problem hiding this comment.
I am not entirely familiar with the chained scopes of macro_rules!, but I can assume there are no cycles, so this should be correct.
Example chain:
A -> B -> C -> D -> E
If multiple threads try to compress the path A -> E starting at A, then no matter the ordering, they will always end up at E.
t1reads nodeAand writes on that nodeB, thent2will readB.t1andt2read nodeA, both will then writeB, which is the result we expect.
I see it as a recursive property as well, so it will hold until both threads read E in their last step.
If multiple threads are compressing on the same path, their results will be the same as well. For example: t1 compresses A -> E and t2 will compress C -> E.
Since both only overwrite their respective nodes, A for t1 and C for t2, they can never interfere with each other. It doesn't matter what t2 is doing on its path, because for t1 the full path still "exists", if t2 managed to overwrite C before t1 gets to it, it just does one step less.
There was a problem hiding this comment.
I'm still not convinced.
Assume we have a slow thread t_slow and a fast thread t_fast.
-
- The slow thread arrives first and reads a
MacroRulesScope::Invocationinscope = *next.borrow();.
- The slow thread arrives first and reads a
-
- Then the fast thread arrives and compresses the whole chain eliminating the
MacroRulesScope::Invocationfrom the step 1 in particular
- Then the fast thread arrives and compresses the whole chain eliminating the
-
- Then the slow thread continues and does
macro_rules_scope.set(scope);puttingMacroRulesScope::Invocationback into themacro_rules_scopeagain.
- Then the slow thread continues and does
-
- In the meantime the fast thread continues assuming that the chain is fully compressed and there're no expanded
MacroRulesScope::Invocations -> "never observe invocation scopes for macros that were already expanded" invariant from the comment above is broken.
- In the meantime the fast thread continues assuming that the chain is fully compressed and there're no expanded
… parallel loop for import resolution. + impl `DynSend`/`DynSync` for all relevant data structures + safety comments.
…` and `RwLock` instead`
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
Force-pushed to keep up to date (and remove i'll wait on #158845 (comment), so i'll mark this @rustbot ready. |
| } | ||
| } | ||
|
|
||
| /// A wrapper around a [`RefCell`] that only allows writes (mutable borrows) based on a condition in the resolver. |
There was a problem hiding this comment.
Lost a comment.
| scope = next.get(); | ||
| macro_rules_scope.set(scope); | ||
| scope = *next.borrow(); | ||
| *macro_rules_scope.borrow_mut() = scope; |
There was a problem hiding this comment.
I'm still not convinced.
Assume we have a slow thread t_slow and a fast thread t_fast.
-
- The slow thread arrives first and reads a
MacroRulesScope::Invocationinscope = *next.borrow();.
- The slow thread arrives first and reads a
-
- Then the fast thread arrives and compresses the whole chain eliminating the
MacroRulesScope::Invocationfrom the step 1 in particular
- Then the fast thread arrives and compresses the whole chain eliminating the
-
- Then the slow thread continues and does
macro_rules_scope.set(scope);puttingMacroRulesScope::Invocationback into themacro_rules_scopeagain.
- Then the slow thread continues and does
-
- In the meantime the fast thread continues assuming that the chain is fully compressed and there're no expanded
MacroRulesScope::Invocations -> "never observe invocation scopes for macros that were already expanded" invariant from the comment above is broken.
- In the meantime the fast thread continues assuming that the chain is fully compressed and there're no expanded
|
Could you move the |
View all comments
Follow up of #159440. This pr implements the parallel part of
par_for_each_slice. And implementsDynSendandDynSyncforRefOrMutandCmCellto make the call topar_for_each_slicecompile.This is the bare minimum to make the parallel loop work and is not at all optimized, this will follow :).
r? @petrochenkov